package sub

import (
	"fmt"
	"io"
	"net/http"
	"os"
	"path/filepath"
	"quipus/cmd/qpc/sub"
	"quipus/internal/utils"
	v1pb "quipus/proto/gen/api/v1"
	"unicode/utf8"

	"github.com/h2non/filetype"
	"github.com/spf13/cobra"
)

var (
	filebae string
)

func init() {
	createCmd.PersistentFlags().StringVarP(&filebae, "file", "f", "", "file path")
	resourceCmd.AddCommand(createCmd)
}

func isTextFile(buffer []byte) bool {
	// 检查是否为 UTF-8 编码
	if !utf8.Valid(buffer) {
		return false
	}

	// 检查是否包含控制字符（除了常见的换行、制表符等）
	for _, b := range buffer {
		if b == 0x00 {
			return false // 包含空字节，可能是二进制文件
		}
		if b < 0x08 && b != 0x09 && b != 0x0A && b != 0x0D {
			return false
		}
	}

	// 检查文本字符的比例
	textChars := 0
	for _, b := range buffer {
		if (b >= 0x20 && b <= 0x7E) || b == 0x09 || b == 0x0A || b == 0x0D {
			textChars++
		}
	}

	// 如果可打印字符占比超过 90%，认为是文本文件
	return float64(textChars)/float64(len(buffer)) > 0.9
}

func GetFileTypeByMIME(filename string) (string, error) {
	fmt.Println("GetFileTypeByMIME")
	file, err := os.Open(filename)
	if err != nil {
		fmt.Println("Error opening file:", err, "   filename:", filename)
		return "", err
	}
	defer file.Close()
	header := make([]byte, 512)
	_, err = file.Read(header)
	if err != nil {
		fmt.Println("Error opening file:", err)
		return "", err
	}
	mimeType := http.DetectContentType(header)
	return mimeType, nil
}

func GetFileType(filename string) (string, string, error) {
	// 打开文件
	file, err := os.Open(filename)
	if err != nil {
		return "", "", err
	}
	defer file.Close()

	// 读取文件头部
	buffer := make([]byte, 512)
	_, err = file.Read(buffer)
	if err != nil && err != io.EOF {
		return "", "", err
	}

	// 首先使用 filetype 检测
	kind, err := filetype.Match(buffer)
	if err != nil {
		return "", "", err
	}

	if kind == filetype.Unknown {
		// 获取文件扩展名
		ext := filepath.Ext(filename)

		// 检查是否为文本文件
		if isTextFile(buffer) {
			switch ext {
			case ".json":
				return "application/json", "json", nil
			case ".xml":
				return "application/xml", "xml", nil
			case ".yaml", ".yml":
				return "application/yaml", "yaml", nil
			case ".md":
				return "text/markdown", "md", nil
			case ".csv":
				return "text/csv", "csv", nil
			case ".html", ".htm":
				return "text/html", "html", nil
			case ".js":
				return "application/javascript", "js", nil
			case ".css":
				return "text/css", "css", nil
			case ".go":
				return "text/x-go", "go", nil
			default:
				// 使用 http.DetectContentType 作为后备
				contentType := http.DetectContentType(buffer)
				if contentType == "text/plain; charset=utf-8" {
					return "text/plain", "txt", nil
				}
				return contentType, ext[1:], nil // 移除扩展名中的点
			}
		}
		return "application/octet-stream", "", nil
	}

	return kind.MIME.Value, kind.Extension, nil
}

var createCmd = &cobra.Command{
	Use:   "create",
	Short: "Run the cmd to create resource",
	RunE: func(cmd *cobra.Command, args []string) error {
		qconn, e := sub.NewGrpcConnect(sub.QpConfig.QPAddress)
		if e != nil {
			return e
		}

		qclient := v1pb.NewResourceServiceClient(qconn)
		ctxWithToken := sub.NewCtxWithToken(sub.QpConfig.Token)
		fmt.Println("filebae: ", filebae)
		resourceType, err := GetFileTypeByMIME(filebae)
		if err != nil {
			return err
		}

		fmt.Println("resourceType: ", resourceType)

		content, err := utils.ReadFile(filebae)
		if err != nil {
			return err
		}
		in := &v1pb.CreateResourceRequest{Filename: filepath.Base(filebae), Type: resourceType, Content: content}

		rsp, err := qclient.CreateResource(ctxWithToken, in)
		if err != nil {
			return err
		}
		fmt.Print(rsp)
		return nil
	},
}
